
#This file has two variable defined by automake: LIB_DIR and DATA_DIR which correspond to something
#like /usr/lib/mmxfer/ and /usr/share/mmxfer. They are used for python modules and interface files respectively.

import sys
import os
import traceback
import threading
import time
import signal

sys.path.append(LIB_DIR)

#test importing of all modules
module_names=[	("gtk","gtk","python-gtk2"),
				("gio","gio","python-gtk2"),
				("gst","gst","python-gst"),
				("mutagen","mutagen","python-mutagen"),
				("simplemtp","simplemtp","simplemtp"),
				]
failed_modules=[]
try:
	import pygtk
	pygtk.require('2.0')
except:
	failed_modules.append("python-gtk2")
try:
	import pygst
	pygst.require('0.10')
	import gst
except:
	failed_modules.append("python-gst")
for module_name in module_names:
	try:
		globals()[module_name[1]]=__import__(module_name[0])
	except:
		if not module_name[2] in failed_modules:
			failed_modules.append(module_name[2])
if len(failed_modules)>0:
	error="Failed to import the following modules:\n\n"
	for module in failed_modules:
		error=error+module+"\n"
	error=error+"\nThese must be installed on your system to use MMXfer."
	#communicate error with stdout, then try gtk, then zenity, then xterm. this is because the user probably isn't running in a console.
	print error
	code=1
	try:#try with gtk
		dlg=gtk.MessageDialog(buttons=gtk.BUTTONS_OK,message_format=error,type=gtk.MESSAGE_ERROR)
		dlg.set_title("MMXfer Error")
		dlg.run()
		code=0
	except:
		pass
	if code is not 0:#try with zenity
		code=os.spawnv(os.P_WAIT,"/usr/bin/env",["/usr/bin/env","zenity","--error","--title=MMXfer Error","--text="+error])
	if code is not 0:#try with xterm
		code=os.spawnv(os.P_WAIT,"/usr/bin/env",["/usr/bin/env","xterm","-e","".join(["echo "+line+";" for line in error.split('\n')])+"read nothing"])
	exit(1)

import mutagen.easyid3

from mmxfer import store
import mmxfer.worker.copy
import mmxfer.worker.transfer
import mmxfer.worker.convert
import mmxfer.worker.update

gtk.gdk.threads_init()

uris=""
try:
	uris=os.environ["NAUTILUS_SCRIPT_SELECTED_URIS"].split()
except:
	uris=sys.argv[1:]
	pass

all_threads=[]
quit_thread=None
class QuitThread(threading.Thread):
	def run(self):
		global all_threads
		for thread in all_threads:
			thread.join()
		gtk.gdk.threads_enter()
		gtk.main_quit()
		gtk.gdk.threads_leave()
def global_quit(*args):
	global liststore
	global quit_thread
	global builder
	liststore.quit_event.set()
	if quit_thread is None:
		quit_thread=QuitThread()
		builder.get_object("cancel").set_property("sensitive",False)
		builder.get_object("MainWindow").set_property("title","MMXfer Closing...")
		quit_thread.start()
	return True#prevent window close

def InitMainWindow():
	builder=gtk.Builder()
	builder.add_from_file(DATA_DIR+"/mmxfer.glade")
	window=builder.get_object("MainWindow")
	#connect destroy signals
	window.connect("delete_event",global_quit)
	builder.get_object("cancel").connect("activate",global_quit)

	#set up the ListStore and CellRenderer columns for the file list
	listview=builder.get_object("treeview")
	listview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
	listview.drag_dest_set(0,[],0)
	liststore=store.Store()
	listview.set_model(liststore)
	listview.append_column(gtk.TreeViewColumn("Name",gtk.CellRendererText(),
												text=store.column("name")))
	listview.append_column(gtk.TreeViewColumn("Progress",gtk.CellRendererProgress(),
												text=store.column("status"),
												value=store.column("progress")))

	#set up the CellRenderer columns for the audio rate:
	ratecombo=builder.get_object("ratecombo")
	cell1=gtk.CellRendererText()
	cell2=gtk.CellRendererText()
	ratecombo.pack_start(cell1, True)
	ratecombo.pack_start(cell2, True)
	ratecombo.add_attribute(cell1, 'text', 0)
	ratecombo.add_attribute(cell2, 'text', 1)
	#add some rates
	ratelist=builder.get_object("mp3rate")

	for rate in [32*i+128 for i in range(7)]:
		ratelist.append((rate,"kbps (CBR)"))
	ratecombo.set_active(2)

	window.set_icon_from_file(DATA_DIR+"/mmxfer.png")

	#give back the builder and its main window
	return builder,window,liststore

builder,window,liststore=InitMainWindow()

#add all files to the transfer store
liststore=builder.get_object("treeview").get_model()
for uri in uris:
	liststore.append(store.build_column(uri))

import signal, os

# Set the signal handler to handle keyboard interrupts
signal.signal(signal.SIGINT, global_quit)

def Start(action,builder):
	builder.get_object("start").set_property("sensitive",False)
	builder.get_object("add_file").set_property("sensitive",False)
	builder.get_object("delete_file").set_property("sensitive",False)
	builder.get_object("ratecombo").set_property("sensitive",False)
	tvm=builder.get_object("treeview").get_model()
	global all_threads
	global liststore
	threads=[]
	threads.append(mmxfer.worker.copy.WorkerThread_Copy(tvm))
	threads.append(mmxfer.worker.transfer.WorkerThread_Transfer(tvm))
	bitrate=192
	bitrate_iter=builder.get_object("ratecombo").get_active_iter()
	if bitrate_iter is not None:
		bitrate=builder.get_object("mp3rate").get_value(bitrate_iter,0)
	threads.append(mmxfer.worker.convert.WorkerThread_Convert(tvm,bitrate))
	threads.append(mmxfer.worker.convert.WorkerThread_Convert(tvm,bitrate))
	for thread in threads:
		thread.start()
	all_threads=all_threads+threads

def Add(action,builder):
	chooser=gtk.FileChooserDialog("Select Audio/Video files to Add", action=gtk.FILE_CHOOSER_ACTION_OPEN,
			buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
	chooser.set_local_only(False)
	chooser.set_select_multiple(True)
	response=chooser.run()
	if response==gtk.RESPONSE_OK:
		global liststore
		for uri in chooser.get_uris():
			liststore.append(store.build_column(uri))
	chooser.hide()
def Remove(action,builder):
	model,list=builder.get_object("treeview").get_selection().get_selected_rows()
	iters=[model.get_iter(path) for path in list]
	for iter in iters:
		model.remove(iter)
def dnd_drop(widget,context,x,y,time,builder):
	widget.drag_get_data(context,"text/uri-list")
	return True
def dnd_motion(widget,context,x,y,time):
	if 'text/uri-list' in context.targets:
		context.drag_status(gtk.gdk.ACTION_COPY,time)
	return True
def dnd_got_data(widget,context,x,y,data,info,time):
	uris=data.get_uris()
	context.finish(True, False, time)
	global liststore
	for uri in uris:
		liststore.append(store.build_column(uri))


builder.get_object("start").connect("activate",Start,builder)
builder.get_object("add_file").connect("activate",Add,builder)
builder.get_object("delete_file").connect("activate",Remove,builder)
builder.get_object("treeview").connect('drag_drop', dnd_drop,builder)
builder.get_object("treeview").connect('drag_motion', dnd_motion)
builder.get_object("treeview").connect('drag_data_received', dnd_got_data)

window.show()

all_threads.append(mmxfer.worker.update.WorkerThread_Update())
all_threads[-1].start()

gtk.main()

for row in liststore:
	for filename in row[store.column("tmp")]:
		try:gio.File(filename).delete()
		except:traceback.print_exc()


